<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Spark • Viewer</title>
  <style>
    * {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      font-family: system-ui, sans-serif;
      color: #fff;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
    }

    .container {
      display: flex;
      align-items: center;
      width: 100%;
      height: 100vh;
      background-color: rgb(43, 41, 40);
      margin: 0;
      padding: 0;
    }

    .drop-container {
      width: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }

    .spark-canvas {
      display: block;
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
    }

    .invisible {
      opacity: 0;
      pointer-events: none;
    }

    .logo {
      position: fixed;
      top: 20px;
      left: 30px;
      z-index: 1;
    }

    .logo img {
      width: 40px;
    }

    .hero-logo {
      text-align: center;
      margin-bottom: 2rem;
    }

    .hero-logo img {
      width: 350px;
      height: auto;
      margin-bottom: 1rem;
    }

    .button,
    .url-input,
    .drop-zone {
      width: 100%;
      max-width: 300px;
      margin: 0.5rem 0;
      padding: 0.75rem;
      border-radius: 6px;
      font-size: 1rem;
      text-align: center;
    }

    .drop-zone {
      max-width: 500px;
      padding-top: 4rem;
      padding-bottom: 4rem;
    }

    .button {
      background-color: transparent;
      color: #ccc;
      border: none;
      cursor: pointer;
    }

    .button:hover {
      background-color: rgb(47, 47, 47);
    }

    .button.upload {
      display: flex;
      align-items: center;
      justify-content: center;
      color: rgb(113, 113, 113);
      line-height: 1em;
    }

    .upload-icon {
      margin-right: 10px;
      height: 1em;
    }

    .url-input {
      background-color: rgb(47, 47, 47);
      border: none;
      color: #fff;
    }

    .drop-zone {
      border: 1px dashed #666;
      color: rgb(89, 89, 89);
      background-color: rgb(47, 47, 47);
    }

    .drop-zone.dragover {
      border: 1px dashed #aaa;
      color: rgb(170, 170, 170);
    }

    @media (min-width: 600px) {
      .button,
      .url-input,
      .drop-zone {
        font-size: 1.1rem;
      }
    }

    .hidden {
      display: none;
    }

    .spz-button {
      position: fixed;
      top: 30px;
      right: 30px;
      display: inline-flex;
      align-items: center;
      gap: 0.4em;
      padding: 0.5em 1.5em;
      background-color: rgb(60, 60, 60);
      border: 0px solid rgb(60, 60, 60);
      border-radius: 0.5em;
      color: #ff6c6c;
      font-family: system-ui, sans-serif;
      font-size: 0.9em;
      cursor: pointer;
      z-index: 1000;
    }

    .spz-button:hover {
      background-color: rgb(90, 90, 90);
    }

    .spz-button .icon {
      display: flex;
      align-items: center;
    }
  </style>
</head>
<body>
  <script type="importmap">
    {
      "imports": {
        "three": "/examples/js/vendor/three/build/three.module.js",
        "three/addons/": "/examples/js/vendor/three/examples/jsm/",
        "@sparkjsdev/spark": "/dist/spark.module.js"
      }
    }
  </script>
  <script type="module">
    import * as THREE from "three";
    import { SplatMesh, transcodeSpz, SparkControls } from "@sparkjsdev/spark";
    import { OrbitControls } from "three/addons/controls/OrbitControls.js";

    const sparkCanvasEl = document.querySelector(".spark-canvas");
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000);
    camera.position.set(0, 0, 1);
    const renderer = new THREE.WebGLRenderer({canvas: sparkCanvasEl});
    const width = sparkCanvasEl.clientWidth;
    const height = sparkCanvasEl.clientHeight;
    var fileName;
    var fileBytes;
    renderer.setSize(width, height, false);

    debugger;
    const controls = new SparkControls({ canvas: sparkCanvasEl });
    // const orbitControls = new OrbitControls(camera, renderer.domElement);
    // orbitControls.target.set(0, 0, 0);
    // orbitControls.minDistance = 0.1;
    // orbitControls.maxDistance = 10;

    function resize() {
      const width = window.innerWidth;
      const height = window.innerHeight;

      // Only resize if necessary
      const canvas = renderer.domElement;
      const needResize = canvas.width !== width || canvas.height !== height;

      if (needResize) {
        renderer.setSize(width, height, false);
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
      }
    }

    window.addEventListener('resize', () => {
      setTimeout(function () { resize(); }, 100);
    });

    renderer.setAnimationLoop(function animate(time) {
      resize();
      // orbitControls.update();
      controls.update(camera);
      renderer.render(scene, camera);
    });

    // Handle drag and drop files.
    const dropZoneEl = document.querySelector('.container');
    const dropUIEl = document.querySelector('.drop-zone');
    const onDragover = function (e) {
      e.preventDefault();
      dropUIEl.classList.add('dragover');
    };
    const onDragLeave = function () {
      dropUIEl.classList.remove('dragover');
    };
    const onDrop = function (e) {
      e.preventDefault();
      dropUIEl.classList.remove('dragover');
      dropUIEl.classList.add('drop');

      const files = e.dataTransfer.files;
      if (files.length > 0) {
        loadSplatFile(files[0]);
      }
    };

    dropZoneEl.addEventListener('dragover', onDragover);
    sparkCanvasEl.addEventListener('dragover', onDragover);

    dropZoneEl.addEventListener('dragleave', onDragLeave);
    sparkCanvasEl.addEventListener('dragleave', onDragLeave);

    dropZoneEl.addEventListener('drop', onDrop);
    sparkCanvasEl.addEventListener('drop', onDrop);

    const fileInput = document.querySelector('#file-input');
    fileInput.onchange = function(event) {
      loadSplatFile(event.target.files[0]);
    };

    async function loadSplatFile(splatFile) {
      fileBytes = new Uint8Array(await splatFile.arrayBuffer());
      fileName = splatFile.name;
      setSplatFile({ fileBytes: fileBytes.slice(), fileName });
    }

    var loadedSplat;
    function setSplatFile(init) {
      if (loadedSplat) { scene.remove(loadedSplat); }

      loadedSplat = new SplatMesh(init);
      loadedSplat.quaternion.set(1, 0, 0, 0);
      scene.add(loadedSplat);

      document.querySelector('.container').classList.add('hidden');
      document.querySelector('.canvas-container').classList.remove('invisible');
    }

    let params = new URLSearchParams(document.location.search);
    let splatURL = params.get("url");

    if (splatURL) { loadSplatURL(splatURL); }


    function loadSplatURL(splatURL) {
      fileName = splatURL.split("/").pop().split("?")[0];
      document.querySelector('.container').classList.add('hidden');
      document.querySelector('.canvas-container').classList.remove('invisible');
      setSplatFile({ url: splatURL });
    }

    const urlFormEl = document.querySelector('.url-form');
    const urlInputEl = document.querySelector('.url-input');
    urlFormEl.addEventListener('submit', function handleEnterKey(event) {
      event.preventDefault();
      const url = new URL(window.location);
      const splatURL = urlInputEl.value;
      loadSplatURL(urlInputEl.value);
      url.searchParams.set('url', splatURL);
      history.pushState(null, '', url);
    });

    document.querySelector('.spz-button').addEventListener('click', async function () {
      const fileInfo =  {
        fileBytes: fileBytes,
        pathOrUrl: fileName,
      };

      const transcodeInfo = {
        inputs: [fileInfo],
        maxSh: 3,
        fractionalBits: 12,
        opacityThreshold: 0
      };
      const transcode = await transcodeSpz(transcodeInfo);
      const blob = new Blob([transcode.fileBytes], { type: "application/octet-stream" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = fileName.split(".")[0] + ".spz";
      a.click();
      URL.revokeObjectURL(url);
    });
  </script>
  <div class="canvas-container invisible">
    <div class="logo">
      <a href="/"><img src="spark-logo.svg" alt="Spark Logo" /></a>
    </div>
    <button class="spz-button">
      <span class="icon" aria-hidden="true">
        <img src="download.svg" width="18" height="18" alt="" />
      </span>
      <span class="label">.spz</span>
    </button>
</button>
    <canvas class="spark-canvas"></canvas>
  </div>
  <div class="container">
    <div class="drop-container">
      <div class="hero-logo">
        <a href="/"><img src="spark-viewer.svg" alt="Spark Viewer Logo" /></a>
      </div>
      <div class="drop-zone">Drag and drop a splat file here</div>
      <label for="file-input" class="button upload"><img class="upload-icon" src="upload-icon.svg" alt="upload" />Choose file</label>
      <input id="file-input" class="hidden" accept=".ply,.spz,.splat,.ksplat,.zip" type="file" />
      <form class="url-form">
        <input class="url-input" type="text" placeholder="Copy splat URL" />
      </form>
    </div>
  </div>
</body>
</html>
